﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace CodeGenLib
{
    public class GenCodeLogic
    {
        private const String NAMESPACE = "#{namespace}";
        private const String HEADER_GUARD = "#{header}";
        private const String INCLUDE = "#{include}";
        private const String CLASS = "#{class}";
        private const String BASE = "#{base}";
        private const String VIRTUAL = "#{virtual}";
        private const String H_FILENAME = "#{h_filename}";

        public GenCodeLogic()
        {
        }

        public void GenHFile(GenParam param, Codes codes)
        {
            codes.Clear();

            String baseLine = this.Bases(param);
            String virtualWord = this.Virtual(param);

            using (StreamReader sr = File.OpenText(this.HTemplateFilename()))
            {
                while (!sr.EndOfStream)
                {
                    String str = sr.ReadLine();
                    if (str.Length == 0)
                    {
                        codes.AddLine("");
                        continue;
                    }

                    int index = str.IndexOf(INCLUDE);
                    if (index != -1)
                    {
                        this.WriteIncludeLines(param, codes);
                    }
                    else
                    {
                        str = str.Replace(NAMESPACE, param.Namespace);
                        str = str.Replace(HEADER_GUARD, param.HeaderGuard);
                        str = str.Replace(CLASS, param.Class);
                        str = str.Replace(BASE, baseLine);
                        str = str.Replace(VIRTUAL, virtualWord);
                        codes.AddLine(str);
                    }
                }
            }
        }

        public void GenCppFile(GenParam param, Codes codes)
        {
            codes.Clear();

            using (StreamReader sr = File.OpenText(this.CppTemplateFilename()))
            {
                while (!sr.EndOfStream)
                {
                    String str = sr.ReadLine();
                    if (str.Length == 0)
                    {
                        codes.AddLine("");
                        continue;
                    }

                    str = str.Replace(NAMESPACE, param.Namespace);
                    str = str.Replace(CLASS, param.Class);
                    str = str.Replace(H_FILENAME, param.HFilename);
                    codes.AddLine(str);
                }
            }
        }

        private void WriteIncludeLines(GenParam param, Codes codes)
        {
            bool hasInclude = false;
            foreach (String include in param.Includes)
            {
                if (include.Length != 0)
                {
                    codes.AddLine("#include " + include);
                    hasInclude = true;
                }
            }

            if (hasInclude)
            {
                codes.AddLine("");
            }
        }

        private String Bases(GenParam param)
        {
            String baseLine = "";

            if (param.Bases.Count != 0)
            {
                bool first = true;
                foreach (String baseClass in param.Bases)
                {
                    if (baseClass.Length == 0)
                    {
                        continue;
                    }

                    if (first)
                    {
                        baseLine += " : ";
                    }
                    else
                    {
                        baseLine += ", ";
                    }

                    baseLine += "public " + baseClass;

                    first = false;
                }
            }

            return baseLine;
        }

        private String Virtual(GenParam param)
        {
            foreach (String baseClass in param.Bases)
            {
                if (baseClass.Length != 0)
                {
                    return "virtual ";
                }
            }
            return "";
        }

        private String HTemplateFilename()
        {
            String mydoc = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            return mydoc + "\\Visual Studio 2008\\Templates\\ItemTemplates\\Visual Cpp\\template.h";
        }

        private String CppTemplateFilename()
        {
            String mydoc = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            return mydoc + "\\Visual Studio 2008\\Templates\\ItemTemplates\\Visual Cpp\\template.cpp";
        }
    }
}
